package cn.com.selfsoft.smartcity.core.controller;

import cn.com.selfsoft.smartcity.commons.enums.ResultCode;
import cn.com.selfsoft.smartcity.commons.exception.EntityExistsException;
import cn.com.selfsoft.smartcity.commons.exception.EntityNotFoundException;
import cn.com.selfsoft.smartcity.commons.exception.OutOfBusinessException;
import cn.com.selfsoft.smartcity.commons.http.ResultModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;

/**
 * 统一捕捉除404的异常
 *
 *
 */
@RestControllerAdvice
public class GenericExceptionController {

    /**
     * 1.追加转换器
     * 2.追加校验器
     *
     * @param binder
     */
    @InitBinder
    public void initBinder(WebDataBinder binder) {
//        System.out.println("统一异常捕捉");
    }

    @Value("${generic.exception.debug-mode:true}")
    private boolean genericExceptionDebugMode;

    private Logger logger = LoggerFactory.getLogger(GenericExceptionController.class);

    /**
     * 参数异常统一处理
     * @param exception
     * @return
     */
    @ResponseBody
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity validationException(MethodArgumentNotValidException exception) {
        BindingResult bindingResult = exception.getBindingResult();
        logger.info("参数异常：" + exception);
        if (bindingResult.hasErrors()) {
            String defaultMessage = bindingResult.getFieldError().getDefaultMessage();
            logger.info("参数异常信息：" + defaultMessage);
            return ResponseEntity.badRequest().body(new ResultModel(ResultCode.BAD_REQUEST.getCode(),ResultCode.BAD_REQUEST.getMessage(),defaultMessage));
        } else {
            logger.info("系统异常：" + exception);
            return ResponseEntity.ok().body(new ResultModel(ResultCode.INTERNAL_SERVER_ERROR));
        }
    }

    /**
     * 统一异常处理
     *
     * @return
     */
    @ExceptionHandler({Exception.class})
    @ResponseBody
    public ResponseEntity<ResultModel> handException(Exception e) {

        if (genericExceptionDebugMode){
            logger.error("Catch Exception：", e);
        }
        return ResponseEntity.ok().body(new ResultModel(ResultCode.INTERNAL_SERVER_ERROR));
    }

    /**
     * 捕捉参数校验异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public ResponseEntity<ResultModel> equals(ConstraintViolationException e) {
        if (genericExceptionDebugMode){
            logger.error("catch ConstraintViolationException：", e);
        }
        return ResponseEntity.ok().body(new ResultModel(ResultCode.BAD_REQUEST.getCode(), e.getMessage()));
    }

    /**
     * 超出业务范围的异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(OutOfBusinessException.class)
    public ResponseEntity<ResultModel> equals(OutOfBusinessException e) {
        return ResponseEntity.ok().body(new ResultModel(ResultCode.OUT_OF_BUSINESS.getCode(), e.getMessage()));
    }

    /**
     * 资源已存在
     *
     * @param e
     * @return
     */
    @ExceptionHandler(EntityExistsException.class)
    public ResponseEntity<ResultModel> equals(EntityExistsException e) {
        return ResponseEntity.ok().body(new ResultModel(ResultCode.OUT_OF_BUSINESS.getCode(), e.getMessage()));
    }

    /**
     * 资源找不到
     *
     * @param e
     * @return
     */
    @ExceptionHandler(EntityNotFoundException.class)
    public ResponseEntity<ResultModel> equals(EntityNotFoundException e) {
        return ResponseEntity.ok().body(new ResultModel(ResultCode.NOT_FOUND.getCode(), e.getMessage()));
    }

}
